//
// Created by jiangpenghui on 2023/6/13.
//

#include <iterator>
#include "algorithm_container.h"

#include<algorithm>


using namespace std;

int integer_item::getA() const {
    return a;
}

void integer_item::setA(int a) {
    integer_item::a = a;
}

// 赋值构造
integer_item integer_item::operator=(const integer_item &rhs) {
    cout << "run = " << endl;
    integer_item::a = rhs.a;
    return *this;
}

bool integer_item::operator==(const integer_item &rhs) const {
    cout << "run operator==" << endl;
    return a == rhs.a;
}

bool integer_item::operator!=(const integer_item &rhs) const {
    cout << "run operator != " << endl;
    return !(rhs == *this);
}

std::ostream &operator<<(std::ostream &os, const integer_item &item) {
    os << "integer_item : {a:" << item.a << "} ";
    return os;
}

integer_item::~integer_item() {

}

integer_item::integer_item(integer_item &&ref) : a(ref.a) {
    cout << "move constructor " << endl;
}

integer_item::integer_item(integer_item &ref) {
    this->a = ref.a;
    cout << "copy constructor" << endl;
}

integer_item::integer_item(int &&a) : a(a) {
    cout << "no && params constructor" << endl;
}

integer_item::integer_item(int &a) : a(a) {
    cout << "one & params constructor" << endl;
}


void operator_integer_item() {
    vector<integer_item> integers;
    integers.push_back(integer_item(2));
    integers.push_back(integer_item());
    integers.push_back(integer_item(-2));
    integers.push_back(integer_item(-2));
    integers.push_back(integer_item(-5));
    integers.push_back(integer_item(-5));
    integers.push_back(integer_item(7));


    for (const auto &item: integers)
        cout << item << endl;


    // 查找容器第一次出现的相同元素，需要重载==操作符
    auto result = adjacent_find(integers.begin(), integers.end());
    if (result == integers.end())
        cout << " No find ele" << endl;
    else
        cout << "ele equal is " << *result << endl;

    auto result2 = adjacent_find(integers.begin(), integers.end(), [](integer_item a, integer_item b) -> bool {
        return a.getA() > b.getA();
    });

    if (result2 == integers.end()) {
        cout << *result2 << endl;
    }

    auto isAllGeZero = std::all_of(integers.begin(), integers.end(), [](auto b) {
        return b.getA() > 0;
    });
    if (isAllGeZero) {
        cout << "all ele is ge zero";
    }



    // 范围中找到的元素等于或者等效于指定的值（排序） binary_search要求元素为数字
    // auto is_search = binary_search(List1.begin(), List1.end(), integer_item(2));
    // 声明vector<integer_item> List1，元素大小为空，无法直接使用
    vector<integer_item> List1(20);
    cout << " vector<integer_item>: capacity is " << List1.capacity() << " size is " << List1.size() << endl;
    List1.push_back(integer_item(23));

    cout << "push_back after : vector<integer_item>: capacity is " << List1.capacity() << " size is " << List1.size()
         << endl;

    // 需要确定List1元素大小，不会自动扩容
    copy(integers.begin(), integers.end(), List1.begin());

    cout << "copy after : vector<integer_item>: capacity is " << List1.capacity() << " size is " << List1.size()
         << endl;


    vector<integer_item> v2(2);

    // 向后复制
    copy_backward(List1.begin(), List1.begin() + 1, v2.end());

    // 倒序复制
    cout << "copy_backward is " << v2.capacity() << " size is " << v2.size()
         << endl;
    for (const auto &item: v2)
        cout << item << endl;


    list<integer_item> list3(7);
    // copy(integers.begin(), integers.end(), list3.begin()); 等效
    copy_backward(integers.begin(), integers.end(), list3.end());

    cout << "list3 = [";
    for (const auto &item: list3)
        cout << item;
    cout << endl;


    list<integer_item> list4(6);
    //按值移动，原值依然存在
    move(integers.rbegin(), integers.rend(), list4.rbegin());

    cout << "list4 is [";
    for (auto item: list4)
        cout << item;
    cout << " ]" << endl;

    cout << "Move after is " << integers.size() << "   " << integers.capacity() << endl;

    for (const auto &item: integers)
        cout << item << endl;


    // 判断两个容器是否相同
    auto is_equal = equal(integers.begin(), integers.end(), list3.begin());

    auto is_range_equal = equal(integers.begin(), integers.end(), list3.begin(), list3.end());
    cout << "is_equal " << is_equal << endl;
    cout << "is_range_equal " << is_range_equal << endl;


    auto find_result = find(integers.begin(), integers.end(), integer_item(2));
    // 查询两个容器最后相同序列
    auto find_end_result = find_end(integers.begin(), integers.end(), list3.begin(), list3.end());
    if (find_result != integers.end())
        cout << "find_result is " << *find_result << endl;

    if (find_end_result == integers.end())
        cout << "no find_end_result" << endl;
    else
        cout << "find_end_result" << *find_end_result << endl;

    cout << "source address is (";
    for (const auto &item: integers)
        cout << &item << " ";
    cout << ")" << endl;


    for_each(integers.begin(), integers.end(), [](auto &item) -> integer_item {
        int a = item.getA();
        item.setA(a * a);
        return move(item);
    });

    cout << "current  address is (";
    for (const auto &item: integers)
        cout << &item << " ";
    cout << ")" << endl;

}

// 判断构造函数执行
void constructor_integer_item() {

    integer_item item;

    // 赋值构造
    integer_item item1 = item;

    // no params constructor  run =
    item = integer_item(2);

    auto item3 = move(item1);


}


